/**
 * Copyright (C) 2016 Hyphenate Inc. All rights reserved.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.srwl.easeui.utils;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spannable;
import android.text.Spannable.Factory;
import android.text.style.ImageSpan;

import com.srwl.easeui.domain.EaseEmojicon;
import com.srwl.easeui.model.EaseDefaultEmojiconDatas;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EmojiManager {
    public static final String DELETE_KEY = "em_delete_delete_expression";

    public static final String ee_1 = "0x1f603";
    public static final String ee_2 = "0x1f600";
    public static final String ee_3 = "0x1f60a";
    public static final String ee_4 = "0x263a";
    public static final String ee_5 = "0x1f609";
    public static final String ee_6 = "0x1f60d";
    public static final String ee_7 = "0x1f618";
    public static final String ee_8 = "0x1f61a";
    public static final String ee_9 = "0x1f61c";
    public static final String ee_10 = "0x1f61d";
    public static final String ee_11 = "0x1f633";
    public static final String ee_12 = "0x1f601";
    public static final String ee_13 = "0x1f614";
    public static final String ee_14 = "0x1f60c";
    public static final String ee_15 = "0x1f612";
    public static final String ee_16 = "0x1f61f";
    public static final String ee_17 = "0x1f61e";
    public static final String ee_18 = "0x1f623";
    public static final String ee_19 = "0x1f622";
    public static final String ee_20 = "0x1f602";
    public static final String ee_1f923 = "0x1f923";
    public static final String ee_1f912 = "0x1f912";
    public static final String ee_1f915 = "0x1f915";
    public static final String ee_1f924 = "0x1f924";
    public static final String ee_1f92e = "0x1f92e";
    public static final String ee_1f976 = "0x1f976";
    public static final String ee_1f911 = "0x1f911";
    public static final String ee_21 = "0x1f62d";
    public static final String ee_22 = "0x1f62a";
    public static final String ee_23 = "0x1f630";
    public static final String ee_24 = "0x1f605";
    public static final String ee_25 = "0x1f613";
    public static final String ee_26 = "0x1f62b";
    public static final String ee_27 = "0x1f629";
    public static final String ee_28 = "0x1f628";
    public static final String ee_29 = "0x1f631";
    public static final String ee_30 = "0x1f621";
    public static final String ee_31 = "0x1f624";
    public static final String ee_32 = "0x1f616";
    public static final String ee_33 = "0x1f606";
    public static final String ee_34 = "0x1f60b";
    public static final String ee_35 = "0x1f637";
    public static final String ee_36 = "0x1f60e";
    public static final String ee_37 = "0x1f634";
    public static final String ee_38 = "0x1f632";
    public static final String ee_39 = "0x1f635";
    public static final String ee_40 = "0x1f608";
    public static final String ee_41 = "0x1f47f";
    public static final String ee_42 = "0x1f62f";
    public static final String ee_43 = "0x1f62c";
    public static final String ee_44 = "0x1f615";
    public static final String ee_45 = "0x1f636";
    public static final String ee_46 = "0x1f607";
    public static final String ee_47 = "0x1f60f";
    public static final String ee_48 = "0x1f611";
    public static final String ee_49 = "0x1f648";
    public static final String ee_50 = "0x1f649";
    public static final String ee_51 = "0x1f64a";
    public static final String ee_52 = "0x1f47d";
    public static final String ee_53 = "0x1f4a9";
    public static final String ee_54 = "0x1f494";

    public static final String emoji_1f4af = "0x1f4af";
    public static final String emoji_1f573 = "0x1f573";
    public static final String emoji_1f9e0 = "0x1f9e0";
    public static final String emoji_1f47e = "0x1f47e";
    public static final String emoji_1f470 = "0x1f470";
    public static final String ee_55 = "0x1f525";
    public static final String ee_56 = "0x1f4a2";
    public static final String ee_57 = "0x1f4a4";
    public static final String ee_58 = "0x1f4a4";
    public static final String ee_59 = "0x1f6ab";
    public static final String ee_60 = "0x2b50";
    public static final String ee_61 = "0x26a1";
    public static final String ee_62 = "0x1f319";
    public static final String ee_63 = "0x2600";
    public static final String ee_64 = "0x26c5";
    public static final String ee_65 = "0x2601";
    public static final String ee_66 = "0x2744";
    public static final String ee_67 = "0x2614";
    public static final String ee_68 = "0x26c4";

    public static final String ee_69 = "0x1f44d";
    public static final String ee_70 = "0x1f44e";
    public static final String ee_71 = "0x1f91d";
    public static final String ee_72 = "0x1f44c";
    public static final String ee_73 = "0x1f44a";
    public static final String ee_74 = "0x270a";
    public static final String ee_75 = "0x270c";
    public static final String ee_76 = "0x270b";
    public static final String ee_77 = "0x1f64f";
    public static final String ee_78 = "0x261d";
    public static final String ee_79 = "0x1f44f";
    public static final String ee_80 = "0x1f4aa";
    public static final String emoji_0x1f595 = "0x1f595";
    public static final String emoji_1f91f = "0x1f91f";
    public static final String emoji_1f919 = "0x1f919";
    public static final String emoji_1f9b6 = "0x1f9b6";
    public static final String emoji_1f485 = "0x1f485";
    public static final String emoji_1f64c = "0x1f64c";

    public static final String ee_81 = "0x1f46a";
    public static final String ee_82 = "0x1f46b";
    public static final String ee_83 = "0x1f47c";
    public static final String ee_84 = "0x1f434";
    public static final String ee_85 = "0x1f436";
    public static final String ee_86 = "0x1f437";
    public static final String ee_87 = "0x1f47b";
    public static final String ee_88 = "0x1f339";
    public static final String ee_89 = "0x1f33b";
    public static final String ee_90 = "0x1f332";
    public static final String ee_91 = "0x1f384";
    public static final String ee_92 = "0x1f381";


    private static final Factory spannableFactory = Factory
            .getInstance();

    private static final Map<Pattern, Object> emoticons = new HashMap<Pattern, Object>();


    private static final Map<Integer, Integer> mText2Entry = new HashMap<>();

    static {
        EaseEmojicon[] emojicons = EaseDefaultEmojiconDatas.getData();
        for (int i = 0; i < emojicons.length; i++) {
            addPattern(emojicons[i].getEmojiText(), emojicons[i].getIcon());
            mText2Entry.put(Integer.decode(emojicons[i].getEmojiText()), emojicons[i].getIcon());
        }


    }

    /**
     * add text and icon to the map
     *
     * @param emojiText-- text of emoji
     * @param icon        -- resource id or local path
     */
    public static void addPattern(String emojiText, Object icon) {
        emoticons.put(Pattern.compile(Pattern.quote(emojiText)), icon);
    }


    /**
     * replace existing spannable with smiles
     *
     * @param context
     * @param spannable
     * @return
     */
    public static boolean addSmiles(Context context, Spannable spannable) {
        boolean hasChanges = false;
        for (Entry<Pattern, Object> entry : emoticons.entrySet()) {
            Pattern key = entry.getKey();
            Matcher matcher = key.matcher(spannable);
            while (matcher.find()) {
                boolean set = true;
                for (ImageSpan span : spannable.getSpans(matcher.start(),
                        matcher.end(), ImageSpan.class))
                    if (spannable.getSpanStart(span) >= matcher.start()
                            && spannable.getSpanEnd(span) <= matcher.end())
                        spannable.removeSpan(span);
                    else {
                        set = false;
                        break;
                    }
                if (set) {
                    hasChanges = true;
                    Object value = entry.getValue();
                    if (value instanceof String && !((String) value).startsWith("http")) {
                        File file = new File((String) value);
                        if (!file.exists() || file.isDirectory()) {
                            return false;
                        }
                        spannable.setSpan(new ImageSpan(context, Uri.fromFile(file)),
                                matcher.start(), matcher.end(),
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else {
                        spannable.setSpan(new ImageSpan(context, (Integer) value),
                                matcher.start(), matcher.end(),
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                }
            }
        }

        return hasChanges;
    }

    public static Spannable getSmiledText(Context context, CharSequence text) {
        Spannable spannable = spannableFactory.newSpannable(text);
        addSmiles(context, spannable);
        return spannable;
    }

    public static boolean containsKey(String key) {
        boolean b = false;
        for (Entry<Pattern, Object> entry : emoticons.entrySet()) {
            Matcher matcher = entry.getKey().matcher(key);
            if (matcher.find()) {
                b = true;
                break;
            }
        }

        return b;
    }

    public static int getSmilesSize() {
        return emoticons.size();
    }


    public static Drawable getDrawable(Context context, int code) {

        Integer integer = mText2Entry.get(code);
        if (integer == null) {
            return null;
        }
        return context.getResources().getDrawable(integer);
    }

    public static boolean contains(int codePoint) {
        return mText2Entry.containsKey(codePoint);
    }

    public static Integer getEmojiResourceId(int codePoint) {
        return mText2Entry.get(codePoint);
    }
}
